// src/sql/plan/mod.rs
mod planner;

use crate::sql::engine::Transaction;
use crate::sql::executor::ResultSet;
use crate::sql::parser::ast;
use crate::sql::parser::ast::Expression;
use crate::sql::plan::planner::Planner;
use crate::sql::schema::Table;
use crate::error::Result;
use crate::sql::executor::Executor;

// 执行节点
#[derive(Debug, PartialEq)]
pub enum Node {
    // 创建表
    CreateTable {
        schema: Table,
    },

    // 插入数据
    Insert {
        table_name: String,
        columns: Vec<String>,
        values: Vec<Vec<Expression>>,
    },

    // 扫描节点
    Scan {
        table_name: String,
    },
}

// 执行计划定义, 底层是不同类型的执行节点
#[derive(Debug, PartialEq)]
pub struct Plan(pub Node);

impl Plan {
    // 构建执行计划
    pub fn build(stmt: ast::Statement) -> Self {
        Planner::new().build(stmt)
    }
    // 执行
    pub fn execute<T: Transaction>(self, txn: &mut T) -> Result<ResultSet> {
        <dyn Executor<T>>::build(self.0).execute(txn)
    }
}

#[cfg(test)]
mod tests {
    use crate::sql::parser;
    use crate::sql::parser::{ast, Parser};
    use crate::sql::plan::{Node, Plan};


    #[test]
    fn test_parser_create_table() -> crate::error::Result<()> {
        let sql1 = "CREATE TABLE tb1 (
                a int default 100,
                b float not null,
                c varchar null,
                d bool default true
            );
        ";
        let stmt1 = Parser::new(sql1).parse()?;


        let sql2 = "CREATE    TABLE tb1 (
                a int          default 100,
                b  float  not        null,
                c varchar null,
                d   bool       default    true
            );
        ";
        let stmt2 = Parser::new(sql2).parse()?;

        let p1 = Plan::build(stmt1);
        let p2 = Plan::build(stmt2);
        println!("{:?}", p1);
        println!("{:?}", p2);

        assert_eq!(p1, p2);

        let sql3 = "CREATE    tab tb1 (
                a int          default 100,
                b  float  not        null,
                c varchar null,
                d   bool       default    true
            );
        ";

        let stmt3 = Parser::new(sql3).parse();
        assert!(stmt3.is_err());

        Ok(())
    }

    #[test]
    fn test_parser_insert() -> crate::error::Result<()> {
        let sql1 = "INSERT INTO tb1  VALUES (1, 2.0, '3');";
        let stmt1 = Parser::new(sql1).parse()?;
        let p1 = Plan::build(stmt1);
        // println!("{:?}", stmt1);
        assert_eq!(p1,
                   Plan(
                       Node::Insert {
                           table_name: "tb1".to_string(),
                           columns: vec![],
                           values: vec![
                               vec![
                                   ast::Expression::Consts(
                                       ast::Consts::Integer(1)
                                   ),
                                   ast::Expression::Consts(
                                       ast::Consts::Float(2.0)
                                   ),
                                   ast::Expression::Consts(
                                       ast::Consts::String("3".to_string())
                                   ),
                               ]
                           ],
                       })
        );

        let sql2 = "INSERT INTO tb1 (a, b, c)  VALUES (1, 2.0, '3'), (4,2.3,'3');";
        let stmt2 = Parser::new(sql2).parse()?;
        let p2 = Plan::build(stmt2);
        // println!("{:?}", stmt2);
        assert_eq!(p2,
                   Plan(
                       Node::Insert {
                           table_name: "tb1".to_string(),
                           columns: vec!["a".to_string(), "b".to_string(), "c".to_string()],
                           values: vec![
                               vec![
                                   ast::Expression::Consts(
                                       ast::Consts::Integer(1)
                                   ),
                                   ast::Expression::Consts(
                                       ast::Consts::Float(2.0)
                                   ),
                                   ast::Expression::Consts(
                                       ast::Consts::String("3".to_string())
                                   ),
                               ],
                               vec![
                                   ast::Expression::Consts(
                                       ast::Consts::Integer(4)
                                   ),
                                   ast::Expression::Consts(
                                       ast::Consts::Float(2.3)
                                   ),
                                   ast::Expression::Consts(
                                       ast::Consts::String("3".to_string())
                                   ),
                               ],
                           ],
                       }
                   )
        );

        Ok(())
    }

    #[test]
    fn test_parser_select() -> crate::error::Result<()> {
        let sql1 = "SELECT * FROM tb1;";
        let stmt1 = Parser::new(sql1).parse()?;
        let p1 = Plan::build(stmt1);

        assert_eq!(p1,
                   Plan(
                       Node::Scan {
                           table_name: "tb1".to_string(),
                       }
                   )
        );

        Ok(())
    }
}